//////// The Politics of status preservation: Immigration and the knowledge economy class \\\\\\\\

//////// Author: Briitta van Staalduinen \\\\\\\\

//// Description: Replication code for analyses \\\\

//// Dataset: European Social Survey, Rounds 1-10 \\\\

//// Code created: April 18, 2025 \\\\

// Set working directory

// Load data \\

use "ESS_1_10.dta", clear

// Label variables in preparation for output \\

label var eduinc "KE class"

label var winner "KE class (binary)"

label var female "Gender (Woman = 1)"

label var cohort3 "Cohort"

label var agea "Age"

label var skillsp_cent "Skill specificity"

label var esec "Occupation (ESeC)"

label var rankbot3 "Low-income min. share (rank)"

label var ranktop3 "High-income min. share (rank)"

label var rankunemp "Unemployed minority (rank)"

label var ranknonrout "KE minority (rank)"

label var bot3_immi2 "Low-income min. share"

label var top3_immi2 "High-income min. share"

label var unemp_noneu "Unemployed minority"

label var nonrout2_immi2 "KE minority"

label var gincdif "Redistribution"

label var rtcjob "Immigration: Economic"

label var rcltlife "Immigration: Cultural"


////////////////////////////// TABLE A1: ESS summary statistics \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

estpost summarize eduinc winner female cohort3 agea skillsp_cent esec gincdif rtcjob rcltlife bot3_immi2 top3_immi2 unemp_noneu nonrout2_immi2

esttab, cells("count mean(fmt(%8.2f)) sd(fmt(%8.2f)) min(fmt(%8.2f)) max(fmt(%8.2f))") tex ///
nomtitles nonumbers nonote noobs label collabels("N" "Mean" "SD" "Min" "Max") ///
title("ESS Summary statistics")


////////////////////////////// MAIN ANALYSIS, FIGURES 1-3 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

// FIGURE 1, IMMIGRATION: ECONOMIC \\

estimates clear

reghdfe rtcjob c.rankbot3##i.winner female cohort3 agea essround unemp_nat esec reggdp skillsp_cent if immi2 == 0, absorb(country) vce(robust) coeflegend
margins winner, at(rankbot3 == (1(5)50)) post
est store mod1

reghdfe rtcjob c.ranktop3##i.winner female cohort3 agea essround unemp_nat esec reggdp skillsp_cent if immi2 == 0, absorb(country) vce(robust) 
margins winner, at(ranktop3 == (1(5)50)) post
est store mod2

coefplot (mod1, label(Minority share low-income) lp(dash)) (mod2, label(Minority share high-income)), vertical recast(line) ciopts(recast(rarea) fc(%33)) keep(*#1.winner*) xtitle("Region rank", margin(t+2)) title("") ytitle("Oppose immigration: Economic", margin(t-5)) aspect(.8) xlabel(, format(%3.2f)) xlabel(1 "5" 2 "10" 3 "15" 4 "20" 5 "25" 6 "30" 7 "35" 8 "40" 9 "45" 10 "50") ylabel(4.2(.2)5.4) legend(position(6)) name(g1, replace)

reghdfe rtcjob c.rankunemp##i.winner female cohort3 agea essround unemp_nat reggdp esec skillsp_cent if immi2 == 0 , absorb(country) vce(robust) 
margins winner, at(rankunemp == (1(5)50)) post
est store mod3

reghdfe rtcjob c.ranknonrout##i.winner female cohort3 agea essround unemp_nat reggdp esec skillsp_cent if immi2 == 0 , absorb(country) vce(robust)
margins winner, at(ranknonrout == (1(5)50)) post
est store mod4

coefplot (mod3, label(Minority share unemployed) lp(dash)) (mod4, label(Minority share KE employed)), vertical recast(line) ciopts(recast(rarea) fc(%33)) keep(*#1.winner*) xtitle("Region rank", margin(t+2)) title("") ytitle("Oppose immigration: Economic", margin(t-5)) aspect(.8) xlabel(, format(%3.2f)) xlabel(1 "5" 2 "10" 3 "15" 4 "20" 5 "25" 6 "30" 7 "35" 8 "40" 9 "45" 10 "50") ylabel(4.2(.2)5.4) legend(position(6)) name(g2, replace)

graph combine g1 g2, cols(2)


// FIGURE 2, IMMIGRATION: CULTURAL \\

reghdfe rcltlife c.rankbot3##i.winner female cohort3 agea essround unemp_nat reggdp skillsp_cent esec if immi2 == 0, absorb(country) vce(robust) 
margins winner, at(rankbot3 == (1(5)50)) post
est store mod5

reghdfe rcltlife c.ranktop3##i.winner female cohort3 agea essround unemp_nat reggdp skillsp_cent esec if immi2 == 0, absorb(country) vce(robust) 
margins winner, at(ranktop3 == (1(5)50)) post
est store mod6

coefplot (mod5, label(Minority share low-income) lp(dash)) (mod6, label(Minority share high-income)), vertical recast(line) ciopts(recast(rarea) fc(%33)) keep(*#1.winner*) xtitle("Region rank", margin(t+2)) title("") ytitle("Oppose immigration: Cultural", margin(t-5)) aspect(.8) xlabel(, format(%3.2f)) xlabel(1 "5" 2 "10" 3 "15" 4 "20" 5 "25" 6 "30" 7 "35" 8 "40" 9 "45" 10 "50") ylabel(3.2(.2)3.8) legend(position(6)) name(g3, replace) 

reghdfe rcltlife c.rankunemp##i.winner female cohort3 agea essround unemp_nat reggdp skillsp_cent esec if immi2 == 0 , absorb(country) vce(robust) 
margins winner, at(rankunemp == (1(5)50)) post
est store mod7

reghdfe rcltlife c.ranknonrout##i.winner female cohort3 agea essround unemp_nat reggdp skillsp_cent esec if immi2 == 0 , absorb(country) vce(robust)
margins winner, at(ranknonrout == (1(5)50)) post
est store mod8

coefplot (mod7, label(Minority share unemployed) lp(dash)) (mod8, label(Minority share KE employed)), vertical recast(line) ciopts(recast(rarea) fc(%33)) keep(*#1.winner*) xtitle("Region rank", margin(t+2)) title("") ytitle("Oppose immigration: Cultural", margin(t-5)) aspect(.8) xlabel(, format(%3.2f)) xlabel(1 "5" 2 "10" 3 "15" 4 "20" 5 "25" 6 "30" 7 "35" 8 "40" 9 "45" 10 "50") ylabel(3.2(.2)3.8) legend(position(6)) name(g4, replace)

graph combine g3 g4, cols(2)


// FIGURE 3, REDISTRIBUTION \\

reghdfe gincdif c.rankbot3##i.winner female cohort3 agea essround unemp_nat reggdp skillsp_cent esec if immi2 == 0 , absorb(country) vce(robust) 
margins winner, at(rankbot3 == (1(5)50)) post
est store mod9

reghdfe gincdif c.ranktop3##i.winner female cohort3 agea essround unemp_nat reggdp skillsp_cent esec if immi2 == 0 , absorb(country) vce(robust)
margins winner, at(ranktop3 == (1(5)50)) post
est store mod10

coefplot (mod9, label(Minority share low-income) lp(dash)) (mod10, label(Minority share high-income)), vertical recast(line) ciopts(recast(rarea) fc(%33)) keep(*#1.winner*) xtitle("Region rank", margin(t+2)) title("") ytitle("Oppose redistribution", margin(t-5))  xlabel(, format(%3.2f)) xlabel(1 "5" 2 "10" 3 "15" 4 "20" 5 "25" 6 "30" 7 "35" 8 "40" 9 "45" 10 "50") ylabel(2(.2)2.8) legend(position(6)) aspect(.8)  name(g5, replace)

reghdfe gincdif c.rankunemp##i.winner female cohort3 agea essround unemp_nat reggdp skillsp_cent esec if immi2 == 0 , absorb(country) vce(robust) 
margins winner, at(rankunemp == (1(5)50)) post
est store mod11

reghdfe gincdif c.ranknonrout##i.winner female cohort3 agea essround unemp_nat reggdp skillsp_cent esec if immi2 == 0 , absorb(country) vce(robust)
margins winner, at(ranknonrout == (1(5)50)) post
est store mod12

coefplot (mod11, label(Minority share unemployed) lp(dash)) (mod12, label(Minority share KE employed)), vertical recast(line) ciopts(recast(rarea) fc(%33)) keep(*#1.winner*) xtitle("Region rank", margin(t+2)) title("") ytitle("Oppose redistribution", margin(t-5)) aspect(.8) xlabel(, format(%3.2f)) xlabel(1 "5" 2 "10" 3 "15" 4 "20" 5 "25" 6 "30" 7 "35" 8 "40" 9 "45" 10 "50") ylabel(2(.2)2.8) legend(position(6)) name(g6, replace)

graph combine g5 g6, cols(2)


////////////////////////////// ROBUSTNESS CHECKS, APPENDIX TABLES A3-A5 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\


// TABLE A3, IMMIGRATION: ECONOMIC \\

estimates clear

xtmixed rtcjob female cohort3 agea skillsp_cent esec essround c.rankbot3##c.eduinc if immi2 == 0 || country: || region:
estimates store m1, title(Model 1)
xtmixed rtcjob female cohort3 agea skillsp_cent esec essround c.ranktop3##c.eduinc if immi2 == 0 || country: || region:
estimates store m2, title(Model 2)
xtmixed rtcjob female cohort3 agea skillsp_cent esec essround c.rankunemp##c.eduinc if immi2 == 0 || country: || region:
estimates store m3, title(Model 3)
xtmixed rtcjob female cohort3 agea skillsp_cent esec essround c.ranknonrout##c.eduinc if immi2 == 0 || country: || region:
estimates store m4, title(Model 4)

esttab m1 m2 m3 m4, ///
tex cells(b(star fmt(3)) se(par fmt(2))) ///
   legend label varlabels(_cons constant)               ///
   stats(N, fmt(3 0 1) label(Observations)) star(* 0.05 ** 0.01 *** 0.001)


// TABLE A4, IMMIGRATION: CULTURAL \\

estimates clear

xtmixed rcltlife female cohort3 agea skillsp_cent esec essround c.rankbot3##c.eduinc if immi2 == 0 || country: || region:
estimates store m1, title(Model 1)
xtmixed rcltlife female cohort3 agea skillsp_cent esec essround c.ranktop3##c.eduinc if immi2 == 0 || country: || region:
estimates store m2, title(Model 2)
xtmixed rcltlife female cohort3 agea skillsp_cent esec essround c.rankunemp##c.eduinc if immi2 == 0 || country: || region:
estimates store m3, title(Model 3)
xtmixed rcltlife female cohort3 agea skillsp_cent esec essround c.ranknonrout##c.eduinc if immi2 == 0 || country: || region:
estimates store m4, title(Model 4)

esttab m1 m2 m3 m4, ///
tex cells(b(star fmt(3)) se(par fmt(2))) ///
   legend label varlabels(_cons constant)               ///
   stats(N, fmt(3 0 1) label(Observations)) star(* 0.05 ** 0.01 *** 0.001)


// TABLE A5, REDISTRIBUTION \\

estimates clear

xtmixed gincdif female cohort3 agea skillsp_cent esec essround c.rankbot3##c.eduinc if immi2 == 0 || country: || region:
estimates store m1, title(Model 1)
xtmixed gincdif female cohort3 agea skillsp_cent esec essround c.ranktop3##c.eduinc if immi2 == 0 || country: || region:
estimates store m2, title(Model 2)
xtmixed gincdif female cohort3 agea skillsp_cent esec essround c.rankunemp##c.eduinc if immi2 == 0 || country: || region:
estimates store m3, title(Model 3)
xtmixed gincdif female cohort3 agea skillsp_cent esec essround c.ranknonrout##c.eduinc if immi2 == 0 || country: || region:
estimates store m4, title(Model 4)

esttab m1 m2 m3 m4, ///
tex cells(b(star fmt(3)) se(par fmt(2))) ///
   legend label varlabels(_cons constant)               ///
   stats(N, fmt(3 0 1) label(Observations)) star(* 0.05 ** 0.01 *** 0.001)

